﻿using AmuTools;
using Callback;
using OfficeHelper;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Tencent;

namespace xyjc
{
    /// <summary>
    /// App类的配置信息
    /// </summary>
    public class AppConfig
    {
        public string TemplateFile { get; private set; } // 模板文件
        public string ListenPath { get; private set; } // 监听路径
        public string OutputPath { get; private set; } // 输出路径
        public string TemplatePath { get; private set; } // 模板文件所在文件夹

        public string Server { get; private set; } // 服务器名
        public string Database { get; private set; } // 数据库名
        public string Username { get; private set; } // 用户名
        public string Password { get; private set; } // 密码
        public string ConnectionString { get; private set; } // 数据库连接字符串，不建议使用这种方式

        public string FileSavePath { get; private set; } // 文件保存路径，多为Word中的图片文件

        public void SetDatabaseConnection(string conStr)
        {
            ConnectionString = conStr;
            Server = "";
            Database = "";
            Username = "";
            Password = "";
        }

        public void SetDatabaseConnection(string server, string database, string username, string password)
        {
            Server = server;
            Database = database;
            Username = username;
            Password = password;
            ConnectionString = "";
        }

        public void SetFileSavePath(string fileSavePath)
        {
            if (!Directory.Exists(fileSavePath))
            {
                throw new Exception(string.Format("文件夹\"{0}\"不存在", fileSavePath));
            }

            FileSavePath = FormatPath(fileSavePath);
        }

        public void SetTemplateFile(string fileName)
        {
            if(!File.Exists(fileName))
            {
                throw new Exception(string.Format("文件\"{0}\"不存在", fileName));
            }

            TemplateFile = fileName;
        }

        public void SetListenPath(string listenPath)
        {
            if (!Directory.Exists(listenPath))
            {
                throw new Exception(string.Format("文件夹\"{0}\"不存在", listenPath));
            }

            ListenPath = FormatPath(listenPath);
        }

        public void SetOutputPath(string outputPath)
        {
            if (!Directory.Exists(outputPath))
            {
                throw new Exception(string.Format("文件夹\"{0}\"不存在", outputPath));
            }

            OutputPath = FormatPath(outputPath);
        }

        public void SetTemplatePath(string templatePath)
        {
            if (!Directory.Exists(templatePath))
            {
                throw new Exception(string.Format("文件夹\"{0}\"不存在", templatePath));
            }

            TemplatePath = FormatPath(templatePath);
        }

        public void Check()
        {
            if (Server == null ||
                Database == null ||
                Username == null ||
                Password == null ||
                TemplateFile == null ||
                ListenPath == null ||
                OutputPath == null ||
                ConnectionString == null ||
                FileSavePath == null)
            {
                throw new Exception("应用参数错误");
            }
        }

        /// <summary>
        /// 格式化路径，保证路径最后有斜杠
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public string FormatPath(string path)
        {
            if (path == "") return path;

            if (path.Last() != '/' && path.Last() != '\\')
            {
                return path + "/";
            }

            return path;
        }
    }

    /// <summary>
    /// Word转换APP类
    /// </summary>
    public class App
    {
        #region 属性
        private Thread ListeningThread { get; set; } // 执行监听的线程，保持引用防止被清理
        public bool IsListening { get; private set; } // 是否处于监听状态
        private string BaseTemplateConfigFile = "BaseTemplate/template.docx"; // 基础模板，内置不修改
        private WordTemplateConfig BaseTemplateConfig { get; set; } // 基础模板配置信息
        private WordTemplateConfig TemplateConfig { get; set; } // 模板配置信息
        public string rootPath {
            get {
                return Directory.GetCurrentDirectory() + "/";
            }
        }
        private string StoredProceduresPath = "StoredProcedures/"; // 存储过程所在目录，内置不修改
        private SqlHelper DB { get; set; } 
        public List<WordTransRecord> wordTransRecords { get; set; } // 转换记录
        private CallbackHelper<WordTransRecord> TransCallback { get; set; } // 注册的转换回调函数

        public AppConfig Config { get; set; } // 应用配置信息
        private WordHelperRuntime WordRuntime { get; set; }
        #endregion

        #region 构造函数与信息配置
        public App(AppConfig config)
        {
            // 加载应用配置信息
            ReloadConfig(config);

            // 解析基础模板配置信息
            BaseTemplateConfig = WordHelper.GetConfig(BaseTemplateConfigFile);

            // 初始化属性
            wordTransRecords = new List<WordTransRecord>();
            TransCallback = new CallbackHelper<WordTransRecord>();
            IsListening = false;
            WordRuntime = new WordHelperRuntime();
        }

        public void ReloadConfig()
        {
            ReloadConfig(Config);
            TemplateConfig = null; // 因为需要重新获取模板配置信息
        }

        public void ReloadConfig(AppConfig config)
        {
            // 首先自己检测配置参数
            config.Check();
            Config = config;

            // 配置数据库连接助手
            if (config.ConnectionString == "")
            {
                DB = new SqlHelper(config.Server, config.Database, config.Username, config.Password);
            }
            else
            {
                DB = new SqlHelper(config.ConnectionString);
            }
            // 创建数据库，数据库已经存在不会覆盖
            CreateDatabase();
        }

        private void CreateDatabase()
        {
            // 需要指定根据哪些model类创建表
            List<Type> types = new List<Type> { typeof(WordTransRecord) };
            // 读取存放存储过程文件的文件夹，默认为*.text和*.sql
            Dictionary<string, string> sps = DB.GetSqlFiles(StoredProceduresPath);
            DB.CreateDataBase(types, sps);
        }
        #endregion

        #region 监听
        /// <summary>
        /// 开始监听目录，自动完成转换
        /// </summary>
        public void StartListen()
        {
            ListeningThread = new Thread(ListenAction);
            IsListening = true;
            ListeningThread.Start();

        }

        /// <summary>
        /// 停止监听目录
        /// </summary>
        public void StopListen()
        {
            IsListening = false;
        }

        private void ListenAction()
        {
            // 根据配置信息替换指定目录下的文件到输出目录
            while(IsListening)
            {
                DirectoryInfo root = new DirectoryInfo(Config.ListenPath);
                FileInfo[] files = root.GetFiles("*.doc*", SearchOption.AllDirectories);
                foreach(FileInfo file in files)
                {
                    TransWord(file);
                    File.Delete(file.FullName);
                }
            }
        }
        #endregion

        #region 文件转换与订阅
        /// <summary>
        /// 转换指定文件
        /// </summary>
        /// <param name="file"></param>
        public void TransWord(FileInfo file)
        {
            string output_path = Utils.GetDatePath(Config.OutputPath) + Utils.GetRandomName() + file.Extension;
            TransWord(file.FullName, output_path);
        }

        /// <summary>
        /// 根据指定的文件名转换文件
        /// </summary>
        /// <param name="fileName"></param>
        public void TransWord(string fileName)
        {
            FileInfo file = new FileInfo(fileName);
            TransWord(file);
        }

        /// <summary>
        /// 根据指定的文件名转换为指定输出文件
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="outputFileName"></param>
        public void TransWord(string fileName, string outputFileName)
        {
            if(TemplateConfig == null)
            {
                TemplateConfig = WordHelper.GetConfig(Config.TemplateFile);
                TemplateConfig.FileSavePath = Config.FileSavePath;
                TemplateConfig.BuiltInFuncs = new AppBuiltInFuncs(Config);
            }
            // 替换模板，生成文件
            Dictionary<string, string> dic = WordHelper.GetData(fileName, BaseTemplateConfig);
            WordHelper.RenderTemplate(outputFileName, TemplateConfig, dic, WordRuntime);
            // 将记录插入数据库
            WordTransRecord record = new WordTransRecord
            {
                InputPath = fileName,
                OutputPath = outputFileName,
                DateTime = DateTimeEx.GetNowTimeStamp(),
                JsonData = SqlHelper.ObjToJson(dic)
            };

            DB.Insert<WordTransRecord>(record);
            // 将记录记录在记录列表里
            wordTransRecords.Add(record);
            // 执行注册的回调
            TransCallback.Publish(record);
        }

        /// <summary>
        /// 得到当前的进度信息
        /// </summary>
        /// <returns></returns>
        public string GetProgressTip()
        {
            return WordRuntime.GetProgressTip();
        }

        /// <summary>
        /// 订阅转换完毕事件
        /// </summary>
        /// <param name="subscribeName">订阅名</param>
        /// <param name="obj">任意对象</param>
        /// <param name="callback">回调函数</param>
        public void SubscribeTrans(string subscribeName, object obj, Action<WordTransRecord, object> callback)
        {
            TransCallback.Subscribe(subscribeName, obj, callback);
        }

        /// <summary>
        /// 取消某个订阅
        /// </summary>
        /// <param name="subscribeName">订阅名</param>
        public void CancelSubscribeTrans(string subscribeName)
        {
            TransCallback.CancelSubscribe(subscribeName);
        }


        public void SubscribeProgress(string subscribeName, object obj, Action<string, object> callback)
        {
            WordRuntime.ProgressCallback.Subscribe(subscribeName, obj, callback);
        }
        
        public void CancelSubscribePrgress(string subscribeName)
        {
            WordRuntime.ProgressCallback.CancelSubscribe(subscribeName);
        }
        #endregion

        #region 修改模板
        /// <summary>
        /// 得到一个修改模板的实例
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public ModifyWordTemplate GetModifyInstance(string fileName)
        {
            return new ModifyWordTemplate(fileName);
        }
        #endregion
    }

    /// <summary>
    /// 修改模板类
    /// </summary>
    public class ModifyWordTemplate
    {
        public string FileName { get; set; }
        public Dictionary<string, Dictionary<string, string>> StaticKeys { get; set; }

        public ModifyWordTemplate(string fileName)
        {
            FileName = fileName;
            StaticKeys = GetTemplateStaticKeysConfig(fileName);
        }

        public Dictionary<string, Dictionary<string, string>> GetTemplateStaticKeysConfig(string fileName)
        {
            WordTemplateConfig config = WordHelper.GetConfig(fileName);
            Dictionary<string, Dictionary<string, string>> static_keys = new Dictionary<string, Dictionary<string, string>>();
            foreach (var k in config.JsonConfig.keys)
            {
                if (k.Value.ContainsKey("static") && k.Value["static"] == "true")
                {
                    if (!k.Value.ContainsKey("defaultValue"))
                    {
                        k.Value["defaultValue"] = "";
                    }
                    if (!k.Value.ContainsKey("label"))
                    {
                        k.Value["label"] = "";
                    }
                    static_keys.Add(k.Key, k.Value);
                }
            }
            return static_keys;
        }

        public void SaveTemplate(string newFileName = "")
        {
            if (newFileName == "")
            {
                newFileName = FileName;
            }

            WordHelper.ModifyTemplate(FileName, newFileName, StaticKeys);
        }
    }

    /// <summary>
    /// 日期时间辅助拓展
    /// </summary>
    public class DateTimeEx
    {
        // 将时间转为时间戳
        public static string DateTimeToTimeStamp(System.DateTime time)
        {
            System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1, 0, 0, 0, 0));
            long t = (time.Ticks - startTime.Ticks) / 10000;   //除10000调整为13位      
            return t.ToString();
        }
        public static string GetNowTimeStamp()
        {
            return DateTimeToTimeStamp(DateTime.Now);
        }

        public static DateTime TimeStampToDateTime(string timeStamp)
        {
            DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));

            long lTime = long.Parse(timeStamp + "0000");
            TimeSpan toNow = new TimeSpan(lTime);
            return dtStart.Add(toNow);
        }
    }
}
